JSXと<dialog>で組んだmodal window
<dialog>をベースに作った、Preactベースのmodal window
<dialog>とPreactでmodal windowを作ってみるで試して、takker-workflow@0.0.1/next-action-viewerに組み込んだものから、modal windowに必要なコードだけ取り出して貼り付けた
以下のコードに加え、<dialog>内の要素のonClickに
$ const stopPropagation = useCallback((e: Event) => e.stopPropagation(), []);
を指定しておく。これにより<dialog>内をクリックしても閉じられないようにできる
Render Hooksで<dialog>を外に公開してしまうのもありかもしれない
from https://raw.githubusercontent.com/takker99/takker-scheduler/0.9.4/workflow/useDialog.ts
onOpenを廃止、代わりにuseDialogの引数に設定するようにした
import pathは適当に修正すること
code:useDialog.ts
import type { Ref } from "../preact/mod.tsx";
import { useCallback, useEffect, useRef } from "../preact/hooks.ts";
export interface UseDialogInit {
onOpen?: () => void;
onClose?: () => void;
onCancel?: () => void;
};
export interface UseDialogResult {
ref: Ref<HTMLDialogElement>;
open: VoidFunction;
close: VoidFunction;
toggle: VoidFunction;
setOpen: (open: boolean) => void;
}
export const useDialog = (init?: UseDialogInit): UseDialogResult => {
const ref = useRef<HTMLDialogElement>(null);
const open = useCallback(() => {
ref.current?.showModal?.();
init?.onOpen?.();
}, init?.onOpen);
const close = useCallback(() => ref.current?.close?.(), []);
const toggle = useCallback(() => ref.current?.open ? close() : open(), open);
const setOpen = useCallback((open_: boolean) => open_ ? open() : close(), open);
useEffect(() => {
if (!init?.onClose) return;
const onClose = init?.onClose;
ref.current?.addEventListener?.("close", onClose);
return () => { ref.current?.removeEventListener?.("close", onClose); };
}, init?.onClose);
useEffect(() => {
if (!init?.onCancel) return;
const onCancel = init?.onCancel;
ref.current?.addEventListener?.("cancel", onCancel);
return () => { ref.current?.removeEventListener?.("cancel", onCancel); };
}, init?.onCancel);
return { ref, open, close, toggle, setOpen };
};
https://scrapbox-bundler.vercel.app?url=https://scrapbox.io/api/code/takker/JSXと%3Cdialog%3Eで組んだmodal_window/style.css&minify&run
dialog用CSS
code:style.css
dialog::backdrop{
background-color:#000c;
}
dialog {
flex-direction: column;
align-items: center;
row-gap: 10px;
padding: 10px;
background: unset;
margin-top: unset;
margin-bottom: unset;
border: unset;
height: unset;
}
dialogopen {
display: flex;
}
dialog > * {
color: var(--page-text-color, #4a4a4a);
background-color: var(--dropdown-menu-bg, #fff);
border: 1px solid rgba(0,0,0,.2);
border-radius: 6px;
}
@media (min-width: 768px) {
dialog {
padding: 30px 0;
}
}
#2024-07-07 14:17:55
#2024-07-03 16:04:08
#2023-09-26 09:04:07